// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// T [author] rhyme_lph
// p [email]  rhymelph@gmail.com
// e [github] https://github.com/rhymelph

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/user_profile_entity.dart';
import 'package:finance_app/src/http_service/http_setting_service.dart';
import 'package:finance_app/src/http_service/http_user_service.dart';
import 'package:finance_app/src/mixin/single_attach_mixin.dart';
import 'package:finance_app/src/page/dashboard/expense/new_expense_page.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/widgets/bottom_sheet/got_it_tip_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/judge_bottom_sheet.dart';
import 'package:finance_app/src/widgets/bottom_sheet/list_select_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'package:local_auth/local_auth.dart';

class AccountSettingsProvider extends BaseProvider with SingleAttachMixin {
  TextEditingController phoneNumberController = TextEditingController();
  FocusNode phoneNumberFocusNode = FocusNode();
  TextEditingController fullNameController = TextEditingController();
  FocusNode fullNameFocusNode = FocusNode();
  TextEditingController emailController = TextEditingController();
  FocusNode emailFocusNode = FocusNode();
  TextEditingController displayNameController = TextEditingController();
  FocusNode displayNameFocusNode = FocusNode();

  @override
  Future get dataFuture => null;

  @override
  void dispose() {
    super.dispose();
    phoneNumberController.dispose();
    phoneNumberFocusNode.dispose();
  }

  @override
  void initState() {
    super.initState();
    networkPath = Config.userProfile.avatar;
    fullNameController.text = Config.userProfile.name;
    displayNameController.text = Config.userProfile.nickname;
    emailController.text = Config.userProfile.email;
    phoneNumberController.text = Config.userProfile.phoneNumber;
  }

  @override
  void unFocus() {
    obtainContext?.call((context) {
      FocusScope.of(context).requestFocus(FocusNode());
    });
  }

  void onUpdateCountryCode(data) {
    update();
  }

  void onLogout() async {
    obtainContext?.call((context) async {
      final isSuccess = await showLogoutJudgeBottomSheet(context);
      if (isSuccess == true) {
        BaseConfig.dialogBase
            .showLoadingDialog(context: context, text: 'Loading');
        await post(HttpUserService.logout(), onSuccess: (result) async {
          Navigator.of(context).pop();
          await Config.clearConfig();
          Routes.navigateTo(RouterGenProviders.loginPage, clearStack: true);
        }, onError: (int statusCode, String msg, Object error,
            StackTrace stackTrace) async {
          Navigator.of(context).pop();
          await Config.clearConfig();
          Routes.navigateTo(RouterGenProviders.loginPage, clearStack: true);
        });
      }
    });
  }

  void onChangePassword() {
    unFocus();
    Routes.navigateTo(RouterGenProviders.changePasswordPage);
  }

  void enableBiometrics() async {
    unFocus();
    if (!(await LocalAuthentication().isDeviceSupported())) {
      obtainContext?.call((context) {
        showGotItTipBottomSheet(context,
            S.current.your_device_doesn_t_support_fingerprint_recognition);
      });
      return;
    }
    final data = await LocalAuthentication()
        .authenticate(localizedReason: S.current.please_touch_fingerprint);
    if (data == true) {
      if (Config.biometricsEnable != true) {
        RProvider.myProvider.globalMap[ConfigKey.biometricsEnable] = true;
      } else {
        RProvider.myProvider.globalMap[ConfigKey.biometricsEnable] = false;
      }
      await RProvider.myProvider.updateGlobalMap();
    }
  }

  void onUpdatePhoneNumber() {
    unFocus();
    Routes.navigateTo(RouterGenProviders.updatePhoneNumberPage);
  }

  void onUpdateEmail() {
    unFocus();
    Routes.navigateTo(RouterGenProviders.updateEmailPage);
  }

  void onUpdateLoadAvatar() async {
    unFocus();
    if (imagePath != null ||
        networkPath != null &&
            !networkPath.startsWith('data:image/png;base64')) {
      onSelectFile(imagePath,
          onChooseAgain: () {
            obtainContext?.call((context) {
              Navigator.of(context).pop();
            });
            onAddAttachment(
                title: S.current.upload_photo, attachName: S.current.upload);
          },
          againText: S.current.choose_again,
          onRemove: () {
            obtainContext?.call((context) {
              Navigator.of(context).pop();
            });
            imagePath = null;
            networkPath = null;
            update();
          },
          canDelete: false,
          attachments: (networkPath?.isNotEmpty ?? false)
              ? (OcrAttachmentEntity()..url = networkPath)
              : null);
    } else {
      onAddAttachment(
          title: S.current.upload_photo, attachName: S.current.upload);
    }
  }

  void onSave() async {
    unFocus();
    obtainContext?.call((context) {
      FocusScope.of(context).requestFocus(FocusNode());
    });

    final fullName = fullNameController.text;
    if (fullName.isEmpty) {
      showToast(S.current.please_enter_full_name);
      return;
    }

    bool isSuccess = false;

    String avatarUrl = networkPath;
    if (networkPath != null &&
        networkPath.startsWith('data:image/png;base64')) {
      avatarUrl = '';
    }
    if (imagePath != null) {
      final result = await uploadFiles(true);
      if (result != null) {
        avatarUrl = result.url;
      }
    }

    await post(
        HttpUserService.updateMyProfile(
            name: fullName,
            email: emailController.text,
            nickname: displayNameController.text,
            avatar: avatarUrl ?? ''),
        loadingTip: imagePath == null ? S.current.loading : null,
        autoHandler: AutoHandler.Toast, onSuccess: (result) async {
      isSuccess = true;
      final user = getEntityFromResult<UserProfileEntity>(result);
      RProvider.myProvider.globalMap[ConfigKey.userProfile] = user;
      await RProvider.myProvider.updateGlobalMap();
    });
    obtainContext?.call((context) {
      if (imagePath != null) {
        Navigator.of(context).pop();
      }
      if (isSuccess) {
        imagePath = null;
        networkPath = Config.userProfile.avatar;
        update();
        showInformationUpdateSuccessTipBottomSheet(context);
      }
    });
  }

  void onChangeLanguage() {
    obtainContext?.call((context) async {
      final selectedLanguage =
          await showLanguageSelectBottomSheet(context, Config.languageCode);
      if (selectedLanguage != Config.languageCode) {
        BaseConfig.dialogBase
            .showLoadingDialog(context: context, text: 'Loading');
        await post(
            HttpSettingService.updateSettingInfo(
              language: selectedLanguage,
            ), onSuccess: (result) async {
          Config.settingInfo.language = selectedLanguage;
          await RProvider.myProvider.updateGlobalMap();
          Routes.navigateTo(RouterGenProviders.dashboardPage,
              clearStack: true, replace: true);
        });
      }
    });
  }
}
